home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
pascal
/
reform.zip
/
REFORM.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1989-12-24
|
74KB
|
3,003 lines
(*[I=2,P=2,O=78,R+,V+] REFORM Formatter directives*)
PROGRAM REFORM(INPUT, OUTPUT, SOURCE, RESULT);
USES
DOS;
(*
*
* REFORM - A Turbo Pascal Program Formatter (Pretty Printer).
*
* Copyright (C) 1981/1982/1984/1986/1987/1988/1989 - R.A. Highness
*
* Last Updated: 12/24/89 03:20am
*
* While this program is copyrighted, you can make any changes that you
* feel are necessary. This program CANNOT be incorporated into any
* commercial application without the written consent of the author.
* My only request is that if you do make any changes to this source code,
* you MUST make the source available to everyone.
*
* If you have questions/comments/bitches/etcettera, you can contact me at:
*
* CompuServe U.S. Mail FidoNET
* ---------- ------------------ -----------------------
* 76004,3122 3203 Clayton Road Solano College PCUG BBS
* Apartment 14 (707)-437-OPUS (6787)
* Concord, CA 94519 1200/2400 8-N-1
* 1:161/8
*
* REFORM will format a Pascal program (or fragment) according to standardized
* formatting rules.REFORM will also convert the case of the identifiers and
* reserved words to either upper/lower case depending on imbedded formatting
* directives.
*
* The series of formatting directives allow (almost) complete control over
* program formatting.
*
* REFORM does does a complete syntactical check (almost) of the entire
* program as it formats.If REFORM encounters syntactical problems, it will
* abort and will not create an output file. By doing this, REFORM eliminates
* a problem which other formatting programs had of losing track of where
* they were and creating complete nonsense as an output file.The extra
* overhead used by doing a syntactical check of the program takes a
* little longer, but I feel that the extra time involved is well worth it.
*
* Comments in Pascal (as with any language) are always difficult (at best)
* to deal with, and REFORM attempts to deal with them in such a way that the
* user has some control over what happens with the comments.
* The comment handling procedures/functions of REFORM are completely separate
* from the normal formatting, and can be re-written (or deleted) without
* affecting the formatting ability of other areas.
*
*
* Version History:
* ----------------
*
* 03/14/81 - Version 0.001
* Initial version. Runs on CDC Cyber 70 series mainframe.
*
* 04/11/81 - Version 0.010
* Fixed cosmetic changes (typos).
*
* 01/28/82 - Version 0.301
* Formatting modifications, no bug fixes (yet).
*
* 09/13/83 - Version 0.538
* Rewrote a *MAJOR* portion of the formatting code. Added control card
* support. Used by EPA/WAKIM.
*
* 09/30/84 - Version 0.843
* Ported to the Apple ][ under Turbo Pascal. Barely runs (mostly due to
* speed of the Apple ][). Ocassionally crashes. The WHILE and WITH
* statements now do not force a blank line before and after. The block
* header does not output extra blank lines. *NOTE: The programmer MUST
* insert a blank line before the BEGIN statement if one is so desired.
*
* The lexical scanner was re-written to handle Turbo Pascal's hex
* constants, and the Turbo Pascal FILE type was added.
*
* 05/11/85 - Version 1.453
* REFORM now allows nested comments.
*
* 05/20/86 - Version 1.973
* Re-wrote the code for formatting statement comments. Comments in CONST,
* TYPE, and VAR declarations are now aligned to the remark column (initial
* value is 40).All other statement comments are formatted as they were
* before.
*
* 12/21/86 - Version 1.994
* REFORM now handles OVERLAY and INLINE statements correctly.Minor bug
* fixes.
*
* 08/28/87 - Version 2.003
* REFORM now handles the USES statement in Turbo Pascal 4.0/5.0.
*
* 11/21/88 - Version 2.013
* REFORM now will insert a blank line if the BEGIN statement is either the
* first statement after a PROCEDURE/FUNCTION statement, or after the VAR
* statement.
*
* 11/23/88 - Version 2.101
* REFORM now concatenates CASE statements on the same line as the condition
* (if it fits). Minor bugs fixed to make the END statement line up with the
* CASE statements.
*
* 11/27/88 - Version 2.352
* New formatting directive added. K+/- Will "kill" all comments found in
* the input file. It will *NOT* delete compiler directives or formatting
* commands. More than ever, it is IMPARATIVE that all formatting directives
* be put on their own line!
*
* 11/28/88 - Version 2.401
* Added on-line help. To see what formatting directives are available
* type REFORM /? and the help will be shown.
*
* 02/07/89 - Version 2.433
* Minor glitch fixes. No *MAJOR* changes. Mostly cosmetic changes.
*
* 12/24/89 - Version 2.501
* Cosmetic changes. Source commented and cleaned up for initial release.
*
*)
CONST
REFORMVERSION = 'REFORM - Version 2.501 - (C) 1981-1989 R.A. Highness';
MAXLINELEN = 250;
BUFSIZE = 152;
BUFSIZEP1 = 153;
BUFSIZEM1 = 151;
MAXWORDLEN = 9;
NORESWORDS = 45;
DEFAULTOUTLINE = 78;
DEFAULTTABSPACES = 3;
DEFAULTCOMMENTSPACES = 1;
MAXBREAKLEVEL = 4;
FF = 12;
HT = 9;
STRINGBLOCKSIZE = 512;
STRINGBLOCKMAX = 511;
STRINGINDEXMAX = 63;
TABINTERVAL = 6;
TYPE
SYMBOLS = (ABSOLUTESYM, ANDSYM, ARRAYSYM, BEGINSYM, CASESYM, CONSTSYM,
DIVSYM, DOSYM, DOWNTOSYM, ELSESYM, ENDSYM, EXTERNSYM, FILESYM,
FORSYM, FORWARDSYM, FUNCTIONSYM, GOTOSYM, IFSYM, INSYM,
INLINESYM, LABELSYM, MODSYM, NILSYM, NOTSYM, OFSYM, ORSYM,
OVERLAYSYM, PACKEDSYM, PROCEDURESYM, PROGRAMSYM, RECORDSYM,
REPEATSYM, SETSYM, SHLSYM, SHRSYM, STRINGSYM, THENSYM, TOSYM,
TYPESYM, UNTILSYM, USESSYM, VARSYM, WHILESYM, WITHSYM, XORSYM,
PLUS, MINUS, MULT, DIVIDE, BECOMES, PERIOD, COMMA, SEMICOLON,
COLON, EQUAL, RELOP, POINTER, SUBRANGE, APOSTROPHY, OPENPAREN,
CLOSEPAREN, OPENBRACK, CLOSEBRACK, IDENTIFIER, NUMBER, STRCONST,
COMMENT, TEXTEND);
SETOFSYMS = SET OF SYMBOLS;
STRINGTYPE = PACKED ARRAY [1..12] OF CHAR;
WORDTYPE = PACKED ARRAY [1..MAXWORDLEN] OF CHAR;
LENTABLETYPE =
RECORD
LOWINDEX, HIINDEX: 1..NORESWORDS;
END;
LINEINDEX = 0..MAXLINELEN;
ACTIONS = (GRAPHIC, SPACES, BEGINLINE);
BUFFERINDEX = 0..BUFSIZEM1;
CHARBUFFER = ARRAY [BUFFERINDEX] OF
RECORD
CASE ACTIONIS: ACTIONS OF
SPACES, BEGINLINE:
(SPACING: LINEINDEX);
GRAPHIC:
(CHARACTER: CHAR)
END;
COLLOG =
RECORD
LOGCHAR: INTEGER;
LOGCOL: LINEINDEX;
LOGLINE: INTEGER;
END;
BREAKLEV = 0..MAXBREAKLEVEL;
ABORTKIND = (SYNTAX, NESTING, COMFORMAT);
STRINGBLOCKINDEX = 0..STRINGINDEXMAX;
STRINGPIECEINDEX = 0..STRINGBLOCKMAX;
STRINGBLOCK = PACKED ARRAY [STRINGPIECEINDEX] OF CHAR;
VAR
RESVWRD: ARRAY [1..NORESWORDS] OF WORDTYPE;
RESSYMBOL: ARRAY [1..NORESWORDS] OF SYMBOLS;
RESLEN: ARRAY [2..MAXWORDLEN] OF LENTABLETYPE;
UPPERCASE, LOWERCASE: ARRAY [CHAR] OF CHAR;
CH, PREVCH: CHAR;
TIMETODO: LONGINT;
CHARREADCOUNT, CHARWRITECOUNT: LONGINT;
SYMBOL: ARRAY [LINEINDEX] OF CHAR;
SYMLEN: 0..MAXLINELEN;
UNWRITTEN: CHARBUFFER;
OLDEST: BUFFERINDEX;
OVERFLOWS, COMOVERFLOWS, FIRSTCOMOVERFLOW, FIRSTOVERFLOW: 0..MAXINT;
STRINGINDEX: ARRAY [STRINGBLOCKINDEX] OF ^STRINGBLOCK;
SPACEBEFORE, SPACEAFTER, ALPHANUMERICS, PROGSET, BLOCKBEGSYS, STATSET,
CONSTANTS, HEADINGBEGSYS, TYPEBEGSYS, EXPRBEGSYS, RELOPS,
ARITHOPS: SETOFSYMS;
SYMBOLBREAK: ARRAY [BREAKLEV] OF
RECORD
BUFCHAR: INTEGER;
BREAKCOL: LINEINDEX;
END;
SYM, LASTSYM: SYMBOLS;
INDENTSTATE: ARRAY [LINEINDEX] OF LINEINDEX;
INDENTLEVEL: LINEINDEX;
SOURCE, RESULT: TEXT;
OUTPUTLINE, CURRENTLINE, INPUTLINE, OUTLINELEN, ONEHALFLINE, FIVEEIGHTHLINE,
BLANKLINES, COLUMN, TABCOLUMN, CHARCOUNT, INITIALBLANKS, STRINGTOP, INDENT,
PARAGRAFINDENT, STATINDENT, WRITECOL, REMARKCOL, THREEFOURTHLINE,
TABSPACES, CONTINUESPACES, COMMENTSPACES, STATSPERLINE: INTEGER;
UCRESWORDS, LCRESWORDS, UCIDENTS, LCIDENTS, EXPORTMODE, SAVINGBLANKS,
FORMATTING, SYMWRITTEN, ENDLINE, ENDFILE, DOUBLEPERIOD, KILLCOMMENTS,
INTYPEORVARDCL, INDECLARATION, NEWFORMATTING, BUNCHING, INDIRECTIVES,
CONVERTTOTABS, SYMBOLFOUND, NEWINPUTLINE: BOOLEAN;
CONST
DEFAULTEXT = 'PAS';
VAR
CMDSTRING: STRING [80];
CMDLINE: STRING [80];
SOURCEFILENAME, RESULTFILENAME: STRING [8];
SOURCEEXTENSION, RESULTEXTENSION: STRING [3];
PROCEDURE CSI;
VAR
I: INTEGER;
BEGIN
IF PARAMSTR(1) = '/?' THEN
BEGIN
WRITELN(' ', REFORMVERSION);
WRITELN;
WRITELN;
WRITELN(' DIR Directive Description Default');
WRITELN('----- ------------------------- -------');
WRITELN('B+/- BUNCH mode toggle on/off B-');
WRITELN('C+/- CONVERT spaces to tabs C-');
WRITELN('F+/- FORMATTING mode on/off F+');
WRITELN('I=x INDENTATION levels (where');
WRITELN(' x is in the range of 1-9) 3');
WRITELN('K+/- KILL comments - on/off K-');
WRITELN('O=xxx OUTPUT LINE LENGTH (10-250) 78');
WRITELN('P=x PROCEDURE SEPARATION - Lines');
WRITELN(' between Procedures/Functions (1-9) 2');
WRITELN('R+/- RESERVED word conversion to');
WRITELN(' upper or lower case OFF');
WRITELN('V+/- VARIABLE conversion to upper');
WRITELN(' or lower case OFF');
WRITELN('X+/- EXPORTABILITY mode. Removes');
WRITELN(' underscores "_" so programs');
WRITELN(' work properly in other dialects');
WRITELN(' of Pascal X-');
WRITELN;
HALT;
END;
WRITELN(REFORMVERSION);
IF PARAMCOUNT > 0 THEN
CMDLINE := PARAMSTR(1)
ELSE
BEGIN
WRITELN;
WRITELN('CALLING SEQUENCE IS:');
WRITELN;
WRITELN('REFORM <infile>');
WRITELN;
WRITELN('For help on formatting directives, type:');
WRITELN;
WRITELN('REFORM /?');
WRITELN;
HALT;
END;
FOR I := 1 TO LENGTH(CMDLINE) DO
CMDLINE[I] := UPCASE(CMDLINE[I]);
I := POS('.', CMDLINE);
IF I = 0 THEN
BEGIN
SOURCEFILENAME := CMDLINE;
SOURCEEXTENSION := DEFAULTEXT;
END
ELSE
BEGIN
SOURCEFILENAME := COPY(CMDLINE, 1, I - 1);
SOURCEEXTENSION := COPY(CMDLINE, I + 1, 3);
END;
RESULTFILENAME := 'TEMP';
RESULTEXTENSION := '$$$';
ASSIGN(SOURCE, SOURCEFILENAME + '.' + SOURCEEXTENSION);
{$I-}
RESET(SOURCE);
{$I+}
IF IORESULT <> 0 THEN
BEGIN
WRITELN;
WRITELN('Unable to find ', SOURCEFILENAME + '.' + SOURCEEXTENSION,
'.');
HALT;
END;
ASSIGN(RESULT, RESULTFILENAME + '.' + RESULTEXTENSION);
{$I-}
REWRITE(RESULT);
{$I+}
END;
PROCEDURE INITSETS;
BEGIN
SPACEBEFORE := [ABSOLUTESYM, ANDSYM, DIVSYM, DOSYM, DOWNTOSYM, INSYM,
MODSYM, OFSYM, ORSYM, SHLSYM, SHRSYM, THENSYM, TOSYM,
XORSYM, PLUS, MINUS, MULT, DIVIDE, BECOMES, EQUAL, RELOP];
SPACEAFTER := [ABSOLUTESYM, ANDSYM, ARRAYSYM, CASESYM, DIVSYM, DOWNTOSYM,
EXTERNSYM, FORSYM, FUNCTIONSYM, GOTOSYM, IFSYM, INSYM,
INLINESYM, MODSYM, NOTSYM, OFSYM, ORSYM, OVERLAYSYM,
PACKEDSYM, PROCEDURESYM, PROGRAMSYM, SHLSYM, SHRSYM,
STRINGSYM, TOSYM, UNTILSYM, WHILESYM, WITHSYM, XORSYM, PLUS,
MINUS, MULT, DIVIDE, BECOMES, COMMA, SEMICOLON, COLON,
EQUAL, RELOP, COMMENT];
ALPHANUMERICS := [ABSOLUTESYM..XORSYM, IDENTIFIER, NUMBER];
HEADINGBEGSYS := [LABELSYM, USESSYM, CONSTSYM, TYPESYM, VARSYM,
OVERLAYSYM, PROCEDURESYM, FUNCTIONSYM];
BLOCKBEGSYS := HEADINGBEGSYS + [BEGINSYM];
STATSET := [BEGINSYM, IFSYM, CASESYM, WHILESYM, REPEATSYM, FORSYM,
WITHSYM, INLINESYM, GOTOSYM, NUMBER, IDENTIFIER];
CONSTANTS := [NUMBER, IDENTIFIER, STRCONST, PLUS, MINUS, NILSYM];
EXPRBEGSYS := CONSTANTS + [POINTER, NOTSYM, NILSYM, OPENBRACK, OPENPAREN];
ARITHOPS := [PLUS, MINUS, MULT, DIVIDE, DIVSYM, MODSYM];
RELOPS := [EQUAL, RELOP, INSYM];
TYPEBEGSYS := CONSTANTS + [POINTER, SETSYM, RECORDSYM, FILESYM, ARRAYSYM,
OPENPAREN, STRINGSYM] - [NILSYM];
END;
FUNCTION TIME: LONGINT;
VAR
T1, T2, T3, T4: WORD;
BEGIN
GETTIME(T1, T2, T3, T4);
TIME := (T1 * 360) + (T2 * 60) + T3;
END;
PROCEDURE INITRESVWRD;
BEGIN
{[B+]}
RESLEN[2].LOWINDEX := 01; RESLEN[2].HIINDEX := 06;
RESLEN[3].LOWINDEX := 07; RESLEN[3].HIINDEX := 18;
RESLEN[4].LOWINDEX := 19; RESLEN[4].HIINDEX := 26;
RESLEN[5].LOWINDEX := 27; RESLEN[5].HIINDEX := 32;
RESLEN[6].LOWINDEX := 33; RESLEN[6].HIINDEX := 38;
RESLEN[7].LOWINDEX := 39; RESLEN[7].HIINDEX := 41;
RESLEN[8].LOWINDEX := 42; RESLEN[8].HIINDEX := 44;
RESLEN[9].LOWINDEX := 45; RESLEN[9].HIINDEX := 45;
RESVWRD[01] := 'do '; RESSYMBOL[01] := DOSYM;
RESVWRD[02] := 'if '; RESSYMBOL[02] := IFSYM;
RESVWRD[03] := 'in '; RESSYMBOL[03] := INSYM;
RESVWRD[04] := 'of '; RESSYMBOL[04] := OFSYM;
RESVWRD[05] := 'or '; RESSYMBOL[05] := ORSYM;
RESVWRD[06] := 'to '; RESSYMBOL[06] := TOSYM;
RESVWRD[07] := 'and '; RESSYMBOL[07] := ANDSYM;
RESVWRD[08] := 'div '; RESSYMBOL[08] := DIVSYM;
RESVWRD[09] := 'end '; RESSYMBOL[09] := ENDSYM;
RESVWRD[10] := 'for '; RESSYMBOL[10] := FORSYM;
RESVWRD[11] := 'mod '; RESSYMBOL[11] := MODSYM;
RESVWRD[12] := 'nil '; RESSYMBOL[12] := NILSYM;
RESVWRD[13] := 'not '; RESSYMBOL[13] := NOTSYM;
RESVWRD[14] := 'set '; RESSYMBOL[14] := SETSYM;
RESVWRD[15] := 'shl '; RESSYMBOL[15] := SHLSYM;
RESVWRD[16] := 'shr '; RESSYMBOL[16] := SHRSYM;
RESVWRD[17] := 'var '; RESSYMBOL[17] := VARSYM;
RESVWRD[18] := 'xor '; RESSYMBOL[18] := XORSYM;
RESVWRD[19] := 'case '; RESSYMBOL[19] := CASESYM;
RESVWRD[20] := 'else '; RESSYMBOL[20] := ELSESYM;
RESVWRD[21] := 'file '; RESSYMBOL[21] := FILESYM;
RESVWRD[22] := 'goto '; RESSYMBOL[22] := GOTOSYM;
RESVWRD[23] := 'then '; RESSYMBOL[23] := THENSYM;
RESVWRD[24] := 'type '; RESSYMBOL[24] := TYPESYM;
RESVWRD[25] := 'uses '; RESSYMBOL[25] := USESSYM;
RESVWRD[26] := 'with '; RESSYMBOL[26] := WITHSYM;
RESVWRD[27] := 'array '; RESSYMBOL[27] := ARRAYSYM;
RESVWRD[28] := 'begin '; RESSYMBOL[28] := BEGINSYM;
RESVWRD[29] := 'const '; RESSYMBOL[29] := CONSTSYM;
RESVWRD[30] := 'label '; RESSYMBOL[30] := LABELSYM;
RESVWRD[31] := 'until '; RESSYMBOL[31] := UNTILSYM;
RESVWRD[32] := 'while '; RESSYMBOL[32] := WHILESYM;
RESVWRD[33] := 'downto '; RESSYMBOL[33] := DOWNTOSYM;
RESVWRD[34] := 'inline '; RESSYMBOL[34] := INLINESYM;
RESVWRD[35] := 'packed '; RESSYMBOL[35] := PACKEDSYM;
RESVWRD[36] := 'record '; RESSYMBOL[36] := RECORDSYM;
RESVWRD[37] := 'repeat '; RESSYMBOL[37] := REPEATSYM;
RESVWRD[38] := 'string '; RESSYMBOL[38] := STRINGSYM;
RESVWRD[39] := 'forward '; RESSYMBOL[39] := FORWARDSYM;
RESVWRD[40] := 'overlay '; RESSYMBOL[40] := OVERLAYSYM;
RESVWRD[41] := 'program '; RESSYMBOL[41] := PROGRAMSYM;
RESVWRD[42] := 'absolute '; RESSYMBOL[42] := ABSOLUTESYM;
RESVWRD[43] := 'external '; RESSYMBOL[43] := EXTERNSYM;
RESVWRD[44] := 'function '; RESSYMBOL[44] := FUNCTIONSYM;
RESVWRD[45] := 'procedure'; RESSYMBOL[45] := PROCEDURESYM;
{[B-]}
END;
PROCEDURE INITIALIZE;
VAR
P: INTEGER;
C: CHAR;
S: STRINGBLOCKINDEX;
BEGIN
TIMETODO := TIME;
INITSETS;
FOR C := CHR(0) TO CHR(127) DO
BEGIN
LOWERCASE[C] := C;
UPPERCASE[C] := C;
END;
FOR C := 'A' TO 'Z' DO
BEGIN
LOWERCASE[C] := CHR(ORD(C) + ORD('a') - ORD('A'));
UPPERCASE[CHR(ORD(C) + ORD('a') - ORD('A'))] := C;
END;
CHARCOUNT := 0;
OUTLINELEN := DEFAULTOUTLINE;
TABSPACES := DEFAULTTABSPACES;
CONTINUESPACES := (TABSPACES + 1) DIV 2;
COMMENTSPACES := DEFAULTCOMMENTSPACES;
INDENTLEVEL := 0;
ONEHALFLINE := OUTLINELEN DIV 2;
FIVEEIGHTHLINE := 5 * OUTLINELEN DIV 8;
THREEFOURTHLINE := 3 * OUTLINELEN DIV 4;
STATSPERLINE := 1;
FOR P := 1 TO OUTLINELEN DO
SYMBOL[P] := ' ';
SYMLEN := 0;
INDENT := 0;
PARAGRAFINDENT := 1;
STATINDENT := 0;
WRITECOL := 0;
REMARKCOL := 40;
SAVINGBLANKS := FALSE;
COLUMN := 0;
TABCOLUMN := 0;
OUTPUTLINE := 1;
CURRENTLINE := 0;
INPUTLINE := 1;
CHARREADCOUNT := 0;
CHARWRITECOUNT := 0;
NEWINPUTLINE := TRUE;
BLANKLINES := 0;
SYM := PERIOD;
KILLCOMMENTS := FALSE;
INDIRECTIVES := FALSE;
ENDLINE := FALSE;
ENDFILE := FALSE;
LASTSYM := PERIOD;
SYMWRITTEN := FALSE;
CH := ' ';
PREVCH := ' ';
INTYPEORVARDCL := FALSE;
INDECLARATION := FALSE;
DOUBLEPERIOD := FALSE;
FORMATTING := TRUE;
NEWFORMATTING := TRUE;
UCRESWORDS := FALSE;
LCRESWORDS := FALSE;
UCIDENTS := FALSE;
LCIDENTS := FALSE;
EXPORTMODE := FALSE;
BUNCHING := FALSE;
CONVERTTOTABS := FALSE;
OVERFLOWS := 0;
COMOVERFLOWS := 0;
INITRESVWRD;
FOR S := 0 TO STRINGINDEXMAX DO
STRINGINDEX[S] := NIL;
STRINGTOP := 0;
END;
PROCEDURE BACKUPSOURCE;
VAR
F: TEXT;
BEGIN
ASSIGN(F, SOURCEFILENAME + '.OLD');
{$I-}
RESET(F);
{$I+}
IF IORESULT = 0 THEN
BEGIN
CLOSE(F);
ERASE(F);
END;
RENAME(SOURCE, SOURCEFILENAME + '.OLD');
END;
PROCEDURE QUIT;
VAR
SECONDS: LONGINT;
BEGIN
CLOSE(SOURCE);
CLOSE(RESULT);
BACKUPSOURCE;
RENAME(RESULT, SOURCEFILENAME + '.' + SOURCEEXTENSION);
IF OVERFLOWS > 0 THEN
BEGIN
WRITE('Line too wide to output in ', OVERFLOWS: 1, ' place');
IF OVERFLOWS > 1 THEN
WRITE('s');
WRITELN('.');
WRITELN('The first error was on line ', FIRSTOVERFLOW: 1, '.');
END;
IF COMOVERFLOWS > 0 THEN
BEGIN
WRITE('Comment too wide to output in ', COMOVERFLOWS: 1, ' place');
IF COMOVERFLOWS > 1 THEN
WRITE('s');
WRITELN('.');
WRITELN('The first error was on line ', FIRSTCOMOVERFLOW: 1, '.');
END;
SECONDS := TIME - TIMETODO;
WRITELN('REFORM complete.');
WRITELN;
WRITE('Time to complete: ');
IF SECONDS > 60 THEN
BEGIN
WRITE(SECONDS DIV 60, ' minute');
IF (SECONDS DIV 60 > 1) THEN
WRITE('s');
WRITE(SECONDS MOD 60);
END
ELSE
WRITE(SECONDS);
WRITE(' second');
IF SECONDS > 1 THEN
WRITE('s');
WRITELN('.');
WRITELN;
WRITE(INPUTLINE - 1: 1, ' line');
IF INPUTLINE - 1 > 1 THEN
WRITE('s');
WRITELN(' (', CHARREADCOUNT: 1, ' characters) read.');
WRITE(OUTPUTLINE - 1: 1, ' line');
IF OUTPUTLINE > 2 THEN
WRITE('s');
WRITELN(' (', CHARWRITECOUNT + 1: 1, ' characters) written.');
END;
PROCEDURE CLEARBREAKS;
VAR
I: BREAKLEV;
BEGIN
FOR I := 0 TO MAXBREAKLEVEL DO
SYMBOLBREAK[I].BUFCHAR := 0;
END;
PROCEDURE RESETCHARCOUNT;
BEGIN
IF CHARCOUNT > BUFSIZEP1 THEN
CHARCOUNT := CHARCOUNT MOD BUFSIZE + 2 * BUFSIZE;
CLEARBREAKS;
END;
PROCEDURE WRITEA(CH: CHAR);
VAR
I: LINEINDEX;
BEGIN
CHARCOUNT := CHARCOUNT + 1;
OLDEST := CHARCOUNT MOD BUFSIZE;
WITH UNWRITTEN[OLDEST] DO
BEGIN
IF CHARCOUNT >= BUFSIZEP1 THEN
IF ACTIONIS = GRAPHIC THEN
BEGIN
IF SAVINGBLANKS THEN
IF CHARACTER = ' ' THEN
INITIALBLANKS := INITIALBLANKS + 1
ELSE
BEGIN
WHILE CONVERTTOTABS AND (INITIALBLANKS >= TABINTERVAL) DO
BEGIN
WRITE(RESULT, CHR(HT));
CHARWRITECOUNT := CHARWRITECOUNT + 1;
INITIALBLANKS := INITIALBLANKS - TABINTERVAL;
END;
WHILE INITIALBLANKS > 0 DO
BEGIN
WRITE(RESULT, ' ');
CHARWRITECOUNT := CHARWRITECOUNT + 1;
INITIALBLANKS := INITIALBLANKS - 1;
END;
SAVINGBLANKS := FALSE;
WRITE(RESULT, CHARACTER);
CHARWRITECOUNT := CHARWRITECOUNT + 1;
END
ELSE
BEGIN
WRITE(RESULT, CHARACTER);
CHARWRITECOUNT := CHARWRITECOUNT + 1;
END
END
ELSE IF ACTIONIS = SPACES THEN
BEGIN
IF SAVINGBLANKS THEN
INITIALBLANKS := INITIALBLANKS + SPACING
ELSE
FOR I := 1 TO SPACING DO
BEGIN
WRITE(RESULT, ' ');
CHARWRITECOUNT := CHARWRITECOUNT + 1;
END;
END
ELSE
BEGIN
IF CHARCOUNT > BUFSIZEP1 THEN
BEGIN
WRITELN(RESULT);
CHARWRITECOUNT := CHARWRITECOUNT + 1;
END;
SAVINGBLANKS := TRUE;
INITIALBLANKS := SPACING;
OUTPUTLINE := OUTPUTLINE + 1;
END;
ACTIONIS := GRAPHIC;
CHARACTER := CH;
IF CH = CHR(HT) THEN
WRITECOL := ((WRITECOL + TABINTERVAL) DIV TABINTERVAL) * TABINTERVAL
ELSE
WRITECOL := WRITECOL + 1;
END;
END;
PROCEDURE NEWLINE(INDENT: LINEINDEX);
BEGIN
ENDLINE := FALSE;
WRITEA(' ');
WITH UNWRITTEN[OLDEST] DO
BEGIN
ACTIONIS := BEGINLINE;
SPACING := INDENT;
END;
WRITECOL := INDENT;
CURRENTLINE := CURRENTLINE + 1;
END;
PROCEDURE PRINTLINE(INDENT: INTEGER);
BEGIN
IF FORMATTING THEN
BEGIN
WHILE (BLANKLINES > 0) AND (CURRENTLINE > 0) DO
BEGIN
NEWLINE(0);
BLANKLINES := 0;
END;
NEWLINE(INDENT);
END;
BLANKLINES := 0;
CLEARBREAKS;
END;
PROCEDURE SPACE(N: INTEGER);
BEGIN
IF FORMATTING THEN
BEGIN
WRITEA(' ');
WITH UNWRITTEN[OLDEST] DO
BEGIN
ACTIONIS := SPACES;
IF N >= 0 THEN
SPACING := N
ELSE
SPACING := 0;
END;
WRITECOL := WRITECOL + N - 1;
END;
END;
PROCEDURE FLUSHBUFFER;
VAR
I: 0..BUFSIZEM1;
BEGIN
FOR I := 0 TO BUFSIZEM1 DO
WRITEA(' ');
WRITELN(RESULT);
END;
PROCEDURE FLUSHSYMBOL;
VAR
P: LINEINDEX;
BEGIN
IF NOT SYMWRITTEN THEN
FOR P := 1 TO SYMLEN DO
WRITEA(SYMBOL[P]);
END;
PROCEDURE CHUCKIT(CH: CHAR);
BEGIN
END;
PROCEDURE GETCHAR;
BEGIN
IF COLUMN < TABCOLUMN THEN
BEGIN
COLUMN := COLUMN + 1;
CH := ' ';
IF NOT FORMATTING THEN
WRITEA(' ');
END
ELSE IF NOT EOF(SOURCE) THEN
IF NOT EOLN(SOURCE) THEN
BEGIN
READ(SOURCE, CH);
IF (LENGTH(CH) <> 0) AND (CH <> #13) THEN
BEGIN
CHARREADCOUNT := CHARREADCOUNT + 1;
IF CH = CHR(HT) THEN
BEGIN
TABCOLUMN := ((COLUMN + TABINTERVAL) DIV TABINTERVAL) *
TABINTERVAL;
CH := ' ';
END;
IF NOT FORMATTING THEN
WRITEA(CH);
COLUMN := COLUMN + 1;
END;
END
ELSE
BEGIN
IF NOT (NEWINPUTLINE) THEN
NEWINPUTLINE := TRUE;
COLUMN := 0;
TABCOLUMN := 0;
INPUTLINE := INPUTLINE + 1;
READLN(SOURCE);
CHARREADCOUNT := CHARREADCOUNT + 1;
IF NOT FORMATTING THEN
BEGIN
NEWLINE(0);
RESETCHARCOUNT;
END;
CH := ' ';
END
ELSE
BEGIN
ENDFILE := TRUE;
CH := ' ';
END
END;
PROCEDURE LINEOVERFLOW;
BEGIN
OVERFLOWS := OVERFLOWS + 1;
IF OVERFLOWS = 1 THEN
FIRSTOVERFLOW := CURRENTLINE + 1;
END;
PROCEDURE COMMENTOVERFLOW;
BEGIN
COMOVERFLOWS := COMOVERFLOWS + 1;
IF COMOVERFLOWS = 1 THEN
FIRSTCOMOVERFLOW := CURRENTLINE;
END;
PROCEDURE ABORT(KIND: ABORTKIND);
BEGIN
FLUSHSYMBOL;
WRITEA(CH);
WRITELN;
IF KIND = SYNTAX THEN
WRITE('Syntax error detected, ')
ELSE IF KIND = NESTING THEN
WRITE('too many indentation levels, ')
ELSE
WRITE('could not format comment, ');
WRITELN('processing aborted at line ', INPUTLINE: 1);
CLOSE(RESULT);
HALT;
END;
PROCEDURE INDENTPLUS(DELTA: INTEGER);
BEGIN
IF INDENTLEVEL > MAXLINELEN THEN
ABORT(NESTING);
INDENTLEVEL := INDENTLEVEL + 1;
INDENTSTATE[INDENTLEVEL] := INDENT;
INDENT := INDENT + DELTA;
IF INDENT > OUTLINELEN THEN
INDENT := OUTLINELEN
ELSE IF INDENT < 0 THEN
INDENT := 0;
END;
PROCEDURE UNDENT;
BEGIN
INDENT := INDENTSTATE[INDENTLEVEL];
INDENTLEVEL := INDENTLEVEL - 1;
END;
PROCEDURE SETSYMBOLBREAK(LEVEL: BREAKLEV);
BEGIN
SPACE(0);
WITH SYMBOLBREAK[LEVEL] DO
BEGIN
BUFCHAR := CHARCOUNT;
BREAKCOL := WRITECOL;
END;
END;
PROCEDURE FORMATLINE(INDENT: INTEGER);
BEGIN
PRINTLINE(INDENT);
END;
PROCEDURE MAKEWHITE;
BEGIN
IF FORMATTING AND (BLANKLINES = 0) THEN
BLANKLINES := 1;
END;
PROCEDURE PUTSYM;
VAR
BEFORE: LINEINDEX;
SYMINDENT: INTEGER;
I: LINEINDEX;
L: BREAKLEV;
LASTBREAK: INTEGER;
FUNCTION SPACESBEFORE(THISSYM, OLDSYM: SYMBOLS): LINEINDEX;
BEGIN
IF ((THISSYM IN ALPHANUMERICS) AND (OLDSYM IN ALPHANUMERICS)) OR
(THISSYM IN SPACEBEFORE) OR (OLDSYM IN SPACEAFTER) THEN
SPACESBEFORE := 1
ELSE
SPACESBEFORE := 0;
END;
BEGIN
BEFORE := SPACESBEFORE(SYM, LASTSYM);
IF ENDLINE OR (BEFORE + SYMLEN + WRITECOL > OUTLINELEN) THEN
BEGIN
L := MAXBREAKLEVEL;
WHILE (L > 0) AND (SYMBOLBREAK[L].BUFCHAR = 0) DO
L := L - 1;
WITH SYMBOLBREAK[L] DO
IF NOT ENDLINE AND FORMATTING AND (BUFCHAR > 0) AND
(CHARCOUNT - BUFCHAR < BUFSIZE) AND
(BEFORE + SYMLEN + INDENT + WRITECOL - BREAKCOL <=
OUTLINELEN) THEN
BEGIN
WITH UNWRITTEN[BUFCHAR MOD BUFSIZE] DO
BEGIN
ACTIONIS := BEGINLINE;
SPACING := INDENT
END;
WRITECOL := WRITECOL - BREAKCOL + INDENT;
CURRENTLINE := CURRENTLINE + 1;
LASTBREAK := BUFCHAR;
END
ELSE
BEGIN
SYMINDENT := OUTLINELEN - SYMLEN;
IF SYMINDENT > INDENT THEN
SYMINDENT := INDENT
ELSE IF SYMINDENT < 0 THEN
BEGIN
SYMINDENT := 0;
LINEOVERFLOW
END;
PRINTLINE(SYMINDENT);
LASTBREAK := CHARCOUNT;
END;
FOR L := 0 TO MAXBREAKLEVEL DO
WITH SYMBOLBREAK[L] DO
IF BUFCHAR <= LASTBREAK THEN
BUFCHAR := 0;
END;
IF UNWRITTEN[OLDEST].ACTIONIS = BEGINLINE THEN
BEFORE := 0;
IF BEFORE > 0 THEN
WITH UNWRITTEN[CHARCOUNT MOD BUFSIZE] DO
IF FORMATTING AND (ACTIONIS = SPACES) THEN
BEGIN
WRITECOL := WRITECOL - SPACING + BEFORE;
SPACING := BEFORE;
END
ELSE
SPACE(BEFORE);
IF FORMATTING THEN
FOR I := 1 TO SYMLEN DO
WRITEA(SYMBOL[I]);
LASTSYM := SYM;
SYMWRITTEN := TRUE;
ENDLINE := FALSE;
END;
PROCEDURE BLOCKCOMCHAR(CHARACTER: CHAR);
FORWARD;
PROCEDURE STATCOMCHAR(CHARACTER: CHAR);
FORWARD;
PROCEDURE DOCOMPILERDIRECTIVES(PUTCHIDX: INTEGER);
PROCEDURE COPYIT;
BEGIN
CASE PUTCHIDX OF
1: BLOCKCOMCHAR(CH);
2: STATCOMCHAR(CH);
END;
GETCHAR;
END;
BEGIN
INDIRECTIVES := TRUE;
IF KILLCOMMENTS THEN
BEGIN
IF PREVCH = '{' THEN
WRITEA('{')
ELSE
BEGIN
WRITEA('(');
WRITEA('*');
END;
PREVCH := ' ';
END;
REPEAT
IF (CH <> '}') AND (CH <> '*') THEN
COPYIT;
UNTIL CH IN ['}', '*'];
END;
PROCEDURE DOFORMATTERDIRECTIVES(PUTCHIDX: INTEGER);
VAR
TEMPFLAG: BOOLEAN;
OPTCHAR: CHAR;
PROCEDURE COPYACHAR;
BEGIN
CASE PUTCHIDX OF
1: BLOCKCOMCHAR(CH);
2: STATCOMCHAR(CH);
END;
GETCHAR;
END;
PROCEDURE TOGGLE(VAR SWITCH: BOOLEAN);
BEGIN
CASE CH OF
'+':
BEGIN
SWITCH := TRUE;
COPYACHAR;
END;
'-':
BEGIN
SWITCH := FALSE;
COPYACHAR;
END;
END;
END;
PROCEDURE NUMDIR(VAR VALUE: INTEGER;
MIN, MAX: INTEGER);
VAR
TEMPVAL: INTEGER;
BEGIN
IF CH = '=' THEN
COPYACHAR;
IF (CH >= '0') AND (CH <= '9') THEN
BEGIN
TEMPVAL := 0;
WHILE (CH >= '0') AND (CH <= '9') DO
BEGIN
IF TEMPVAL <= (MAXINT - 9) DIV 10 THEN
TEMPVAL := TEMPVAL * 10 + (ORD(CH) - ORD('0'));
COPYACHAR;
END;
IF TEMPVAL < MIN THEN
TEMPVAL := MIN;
IF TEMPVAL > MAX THEN
TEMPVAL := MAX;
VALUE := TEMPVAL;
END;
END;
BEGIN
INDIRECTIVES := TRUE;
IF KILLCOMMENTS THEN
BEGIN
IF PREVCH = '{' THEN
WRITEA('{')
ELSE
BEGIN
WRITEA('(');
WRITEA('*');
END;
PREVCH := ' ';
END;
COPYACHAR;
REPEAT
IF (CH <> ']') AND (CH <> '}') AND (CH <> '*') THEN
BEGIN
OPTCHAR := CH;
COPYACHAR;
CASE OPTCHAR OF
'b', 'B':
BEGIN
TOGGLE(BUNCHING);
IF BUNCHING THEN
STATSPERLINE := MAXLINELEN
ELSE
STATSPERLINE := 1;
END;
'c', 'C': TOGGLE(CONVERTTOTABS);
'f', 'F': TOGGLE(NEWFORMATTING);
'i', 'I':
BEGIN
NUMDIR(TABSPACES, 1, 9);
CONTINUESPACES := (TABSPACES + 1) DIV 2;
END;
'k', 'K': TOGGLE(KILLCOMMENTS);
'o', 'O':
BEGIN
NUMDIR(OUTLINELEN, 1, MAXLINELEN);
ONEHALFLINE := OUTLINELEN DIV 2;
FIVEEIGHTHLINE := (5 * OUTLINELEN) DIV 8;
THREEFOURTHLINE := (3 * OUTLINELEN) DIV 4;
END;
'p', 'P': NUMDIR(PARAGRAFINDENT, 1, 9);
'r', 'R':
BEGIN
TOGGLE(UCRESWORDS);
LCRESWORDS := NOT (UCRESWORDS);
END;
'v', 'V':
BEGIN
TOGGLE(UCIDENTS);
LCIDENTS := NOT (UCIDENTS);
END;
'x', 'X': TOGGLE(EXPORTMODE);
ELSE;
END;
END;
UNTIL (CH = ']') OR (CH = '}') OR (CH = '*');
IF CH = ']' THEN
COPYACHAR;
END;
VAR
STATBREAK: INTEGER;
STATBLANKS: BOOLEAN;
FIRSTINPUTLINE: BOOLEAN;
PROCEDURE BLOCKCOMCHAR;
BEGIN
IF ENDFILE THEN
ABORT(SYNTAX);
IF (NOT KILLCOMMENTS) OR (INDIRECTIVES) THEN
BEGIN
IF FORMATTING THEN
IF NEWINPUTLINE AND (CHARACTER = ' ') THEN
BEGIN
IF WRITECOL > OUTLINELEN THEN
COMMENTOVERFLOW;
PRINTLINE(COLUMN);
FIRSTINPUTLINE := FALSE;
NEWINPUTLINE := FALSE;
END
ELSE
WRITEA(CHARACTER);
END;
END;
PROCEDURE BREAKSTATCOMMENT;
VAR
EXTRALEN: INTEGER;
COMINDENT: INTEGER;
BEGIN
EXTRALEN := CHARCOUNT - STATBREAK + 1;
IF WRITECOL - EXTRALEN > MAXLINELEN THEN
ABORT(COMFORMAT)
ELSE
BEGIN
IF WRITECOL - EXTRALEN > OUTLINELEN THEN
COMMENTOVERFLOW;
COMINDENT := OUTLINELEN - EXTRALEN;
IF COMINDENT < 0 THEN
COMINDENT := 0
ELSE IF COMINDENT > REMARKCOL THEN
COMINDENT := REMARKCOL;
WITH UNWRITTEN[STATBREAK MOD BUFSIZE] DO
BEGIN
ACTIONIS := BEGINLINE;
SPACING := COMINDENT;
END;
CURRENTLINE := CURRENTLINE + 1;
WRITECOL := COMINDENT + EXTRALEN;
END;
END;
PROCEDURE STATCOMCHAR;
BEGIN
IF ENDFILE THEN
ABORT(SYNTAX);
IF (NOT KILLCOMMENTS) OR (INDIRECTIVES) THEN
BEGIN
IF FORMATTING THEN
IF CHARACTER = ' ' THEN
BEGIN
IF NOT STATBLANKS THEN
BEGIN
IF (WRITECOL > OUTLINELEN) AND (STATBREAK <> 0) THEN
BREAKSTATCOMMENT;
WRITEA(' ');
STATBREAK := CHARCOUNT;
STATBLANKS := TRUE;
END;
END
ELSE
BEGIN
WRITEA(CHARACTER);
STATBLANKS := FALSE;
END;
END;
END;
PROCEDURE DOCOMMENT(BLOCK: BOOLEAN;
INITCOL: LINEINDEX;
INITCHAR: CHAR);
PROCEDURE ADJUSTBLOCKCOMMENT(START: INTEGER);
VAR
COMLENGTH: INTEGER;
COMINDENT: INTEGER;
BEGIN
IF FORMATTING THEN
BEGIN
IF FIRSTINPUTLINE THEN
BEGIN
COMLENGTH := CHARCOUNT - START;
COMINDENT := OUTLINELEN - COMLENGTH;
IF COMINDENT < 0 THEN
COMINDENT := 0
ELSE IF COMINDENT > STATINDENT THEN
COMINDENT := STATINDENT;
UNWRITTEN[START MOD BUFSIZE].SPACING := COMINDENT;
WRITECOL := COMINDENT + COMLENGTH;
END;
IF WRITECOL > OUTLINELEN THEN
COMMENTOVERFLOW;
END;
END;
PROCEDURE ADJUSTSTATCOMMENT;
BEGIN
IF FORMATTING THEN
IF WRITECOL > OUTLINELEN THEN
IF STATBREAK = 0 THEN
IF WRITECOL <= MAXLINELEN THEN
COMMENTOVERFLOW
ELSE
ABORT(COMFORMAT)
ELSE
BREAKSTATCOMMENT;
END;
PROCEDURE BLOCKCOMMENT(COLUMN: LINEINDEX;
INITCHAR: CHAR);
VAR
TERMCHAR1, TERMCHAR2: CHAR;
COMSTART: INTEGER;
BEGIN
PRINTLINE(COLUMN - 1);
COMSTART := CHARCOUNT;
FIRSTINPUTLINE := TRUE;
IF INITCHAR = '{' THEN
BEGIN
TERMCHAR1 := '}';
TERMCHAR2 := '}';
PREVCH := '{';
BLOCKCOMCHAR('{')
END
ELSE
BEGIN
TERMCHAR1 := '*';
TERMCHAR2 := ')';
PREVCH := '*';
BLOCKCOMCHAR('(');
BLOCKCOMCHAR('*');
END;
GETCHAR;
IF CH = '$' THEN
DOCOMPILERDIRECTIVES(1);
IF CH = '[' THEN
DOFORMATTERDIRECTIVES(1);
REPEAT
WHILE CH <> TERMCHAR1 DO
BEGIN
BLOCKCOMCHAR(CH);
GETCHAR;
END;
IF CH = '*' THEN
BEGIN
GETCHAR;
IF CH <> ')' THEN
BLOCKCOMCHAR('*');
END;
UNTIL CH = TERMCHAR2;
IF CH = '}' THEN
BLOCKCOMCHAR('}')
ELSE
BEGIN
BLOCKCOMCHAR('*');
BLOCKCOMCHAR(')');
END;
INDIRECTIVES := FALSE;
IF BLOCK THEN
ADJUSTBLOCKCOMMENT(COMSTART);
END;
PROCEDURE STATCOMMENT(INITCHAR: CHAR);
VAR
TERMCHAR1, TERMCHAR2: CHAR;
BEGIN
STATBREAK := 0;
STATBLANKS := FALSE;
INDENTPLUS(WRITECOL + COMMENTSPACES + 1 - INDENT);
IF INDENT > THREEFOURTHLINE THEN
BEGIN
UNDENT;
INDENTPLUS(TABSPACES);
END;
IF WRITECOL < OUTLINELEN - COMMENTSPACES - 1 THEN
IF INDECLARATION THEN
IF (REMARKCOL - WRITECOL) > COMMENTSPACES THEN
SPACE(REMARKCOL - WRITECOL)
ELSE
SPACE(COMMENTSPACES)
ELSE
SPACE(COMMENTSPACES);
IF INITCHAR = '{' THEN
BEGIN
TERMCHAR1 := '}';
TERMCHAR2 := '}';
STATCOMCHAR('{')
END
ELSE
BEGIN
TERMCHAR1 := '*';
TERMCHAR2 := ')';
STATCOMCHAR('(');
STATCOMCHAR('*');
END;
GETCHAR;
IF CH = '$' THEN
DOCOMPILERDIRECTIVES(2);
IF CH = '[' THEN
DOFORMATTERDIRECTIVES(2);
REPEAT
WHILE CH <> TERMCHAR1 DO
BEGIN
STATCOMCHAR(CH);
GETCHAR;
END;
IF CH = '*' THEN
BEGIN
GETCHAR;
IF CH <> ')' THEN
STATCOMCHAR('*');
END;
UNTIL CH = TERMCHAR2;
IF CH = '}' THEN
STATCOMCHAR('}')
ELSE
BEGIN
STATCOMCHAR('*');
STATCOMCHAR(')');
END;
ADJUSTSTATCOMMENT;
UNDENT;
BLANKLINES := 0;
NEWINPUTLINE := FALSE;
END;
BEGIN
NEWINPUTLINE := FALSE;
IF BLOCK THEN
BLOCKCOMMENT(INITCOL, INITCHAR)
ELSE
STATCOMMENT(INITCHAR);
FORMATTING := NEWFORMATTING;
NEWINPUTLINE := FALSE;
GETCHAR;
WHILE (CH = ' ') AND NOT NEWINPUTLINE DO
GETCHAR;
IF FORMATTING AND NEWINPUTLINE THEN
ENDLINE := TRUE;
SYMBOLFOUND := FALSE;
LASTSYM := COMMENT;
END;
PROCEDURE SYMBOLPUT(THISCHAR: CHAR);
BEGIN
SYMLEN := SYMLEN + 1;
SYMBOL[SYMLEN] := THISCHAR;
GETCHAR;
END;
PROCEDURE PRINTCHAR;
BEGIN
IF WRITECOL >= OUTLINELEN THEN
PRINTLINE(INDENT + CONTINUESPACES);
IF FORMATTING THEN
WRITEA(CH);
GETCHAR;
END;
PROCEDURE SCANBLANKS;
BEGIN
WHILE (CH = ' ') AND NOT ENDFILE DO
GETCHAR;
END;
PROCEDURE STRINGCONSTANT;
VAR
STRINGEND: BOOLEAN;
BEGIN
NEWINPUTLINE := FALSE;
SYMBOLFOUND := TRUE;
SYM := STRCONST;
REPEAT
IF CH = '#' THEN
BEGIN
SYMBOLPUT(CH);
IF CH = '$' THEN
BEGIN
SYMBOLPUT(CH);
WHILE CH IN ['0'..'9', 'A'..'F', 'a'..'f'] DO
SYMBOLPUT(UPPERCASE[CH]);
END
ELSE
WHILE CH IN ['0'..'9'] DO
SYMBOLPUT(CH);
END
ELSE IF CH = '^' THEN
BEGIN
SYMBOLPUT(CH);
IF CH IN ['@'..'_', 'a'..'z'] THEN
SYMBOLPUT(UPPERCASE[CH]);
END
ELSE IF CH = '''' THEN
BEGIN
STRINGEND := FALSE;
REPEAT
SYMBOLPUT(CH);
IF CH = '''' THEN
BEGIN
SYMBOLPUT(CH);
STRINGEND := CH <> '''';
END;
UNTIL NEWINPUTLINE OR STRINGEND;
END;
STRINGEND := (CH <> '#') AND (CH <> '^') AND (CH <> '''');
UNTIL NEWINPUTLINE OR STRINGEND;
IF NOT STRINGEND THEN
ABORT(SYNTAX);
END;
PROCEDURE TESTRESVWRD;
VAR
ID: WORDTYPE;
INDEX: 1..NORESWORDS;
P: 1..MAXWORDLEN;
BEGIN
IF (SYMLEN >= 2) AND (SYMLEN <= MAXWORDLEN) THEN
BEGIN
FOR P := 1 TO MAXWORDLEN DO
IF P > SYMLEN THEN
ID[P] := ' '
ELSE
ID[P] := LOWERCASE[SYMBOL[P]];
WITH RESLEN[SYMLEN] DO
BEGIN
INDEX := LOWINDEX;
WHILE (RESVWRD[INDEX] <> ID) AND (INDEX < HIINDEX) DO
INDEX := INDEX + 1;
END;
IF RESVWRD[INDEX] = ID THEN
SYM := RESSYMBOL[INDEX]
ELSE
SYM := IDENTIFIER;
END
ELSE
SYM := IDENTIFIER;
END;
PROCEDURE SETSYMBOLCASE(KIND: SYMBOLS);
VAR
LASTUNDERSCORE: BOOLEAN;
I, J: LINEINDEX;
BEGIN
IF KIND = IDENTIFIER THEN
BEGIN
IF EXPORTMODE THEN
BEGIN
J := 0;
LASTUNDERSCORE := TRUE;
FOR I := 1 TO SYMLEN DO
IF SYMBOL[I] = '_' THEN
LASTUNDERSCORE := TRUE
ELSE IF LASTUNDERSCORE THEN
BEGIN
LASTUNDERSCORE := FALSE;
J := J + 1;
SYMBOL[J] := UPPERCASE[SYMBOL[I]];
END
ELSE
BEGIN
J := J + 1;
SYMBOL[J] := LOWERCASE[SYMBOL[I]];
END;
FOR I := J + 1 TO SYMLEN DO
SYMBOL[I] := ' ';
SYMLEN := J;
END;
IF UCIDENTS THEN
FOR I := 1 TO SYMLEN DO
SYMBOL[I] := UPPERCASE[SYMBOL[I]]
ELSE IF LCIDENTS THEN
FOR I := 1 TO SYMLEN DO
SYMBOL[I] := LOWERCASE[SYMBOL[I]];
END
ELSE
BEGIN
IF UCRESWORDS THEN
FOR I := 1 TO SYMLEN DO
SYMBOL[I] := UPPERCASE[SYMBOL[I]]
ELSE IF LCRESWORDS THEN
FOR I := 1 TO SYMLEN DO
SYMBOL[I] := LOWERCASE[SYMBOL[I]];
END;
END;
PROCEDURE ALPHACHAR;
BEGIN
NEWINPUTLINE := FALSE;
SYMBOLFOUND := TRUE;
WHILE CH IN ['A'..'Z', 'a'..'z', '0'..'9', '_'] DO
SYMBOLPUT(CH);
TESTRESVWRD;
SETSYMBOLCASE(SYM);
END;
PROCEDURE NUMERICCHAR;
BEGIN
NEWINPUTLINE := FALSE;
SYMBOLFOUND := TRUE;
SYM := NUMBER;
IF CH = '$' THEN
BEGIN
SYMBOLPUT('$');
WHILE CH IN ['0'..'9', 'A'..'F', 'a'..'f'] DO
SYMBOLPUT(UPPERCASE[CH]);
END
ELSE
BEGIN
WHILE (CH >= '0') AND (CH <= '9') DO
SYMBOLPUT(CH);
IF CH = '.' THEN
BEGIN
SYMBOLPUT(CH);
IF CH = '.' THEN
BEGIN
SYMLEN := SYMLEN - 1;
DOUBLEPERIOD := TRUE;
END
ELSE
WHILE (CH >= '0') AND (CH <= '9') DO
SYMBOLPUT(CH);
END;
IF (CH = 'E') OR (CH = 'e') THEN
BEGIN
SYMBOLPUT('E');
IF (CH = '+') OR (CH = '-') THEN
SYMBOLPUT(CH);
WHILE (CH >= '0') AND (CH <= '9') DO
SYMBOLPUT(CH);
END
END;
END;
PROCEDURE SPECIALCHAR;
BEGIN
SYMBOLFOUND := TRUE;
NEWINPUTLINE := FALSE;
CASE CH OF
'+':
BEGIN
SYM := PLUS;
SYMBOLPUT(CH);
END;
'-':
BEGIN
SYM := MINUS;
SYMBOLPUT(CH);
END;
'*':
BEGIN
SYM := MULT;
SYMBOLPUT(CH);
END;
'/':
BEGIN
SYM := DIVIDE;
SYMBOLPUT(CH);
END;
'.':
BEGIN
SYM := PERIOD;
SYMBOLPUT(CH);
IF DOUBLEPERIOD THEN
BEGIN
SYMBOL[2] := '.';
SYMLEN := 2;
SYM := SUBRANGE;
END
ELSE IF CH = '.' THEN
BEGIN
SYM := SUBRANGE;
SYMBOLPUT(CH);
END;
DOUBLEPERIOD := FALSE;
END;
',':
BEGIN
SYM := COMMA;
SYMBOLPUT(CH);
END;
';':
BEGIN
SYM := SEMICOLON;
SYMBOLPUT(CH);
END;
':':
BEGIN
SYM := COLON;
SYMBOLPUT(CH);
IF CH = '=' THEN
BEGIN
SYM := BECOMES;
SYMBOLPUT(CH);
END;
END;
'=':
BEGIN
SYM := EQUAL;
SYMBOLPUT(CH);
END;
'<':
BEGIN
SYM := RELOP;
SYMBOLPUT(CH);
IF (CH = '=') OR (CH = '>') THEN
SYMBOLPUT(CH);
END;
'>':
BEGIN
SYM := RELOP;
SYMBOLPUT(CH);
IF CH = '=' THEN
SYMBOLPUT(CH);
END;
'^':
BEGIN
IF INTYPEORVARDCL OR (LASTSYM IN [IDENTIFIER, CLOSEBRACK]) THEN
BEGIN
SYM := POINTER;
SYMBOLPUT(CH);
END
ELSE
STRINGCONSTANT;
END;
'''', '#': STRINGCONSTANT;
')':
BEGIN
SYM := CLOSEPAREN;
SYMBOLPUT(CH);
END;
'[':
BEGIN
SYM := OPENBRACK;
SYMBOLPUT(CH);
END;
']':
BEGIN
SYM := CLOSEBRACK;
SYMBOLPUT(CH);
END;
END;
END;
PROCEDURE COMMENTCHAR;
VAR
INITCHAR: CHAR;
BEGIN
IF CH = '(' THEN
BEGIN
INITCHAR := CH;
SYMBOLPUT(CH);
IF CH = '*' THEN
BEGIN
SYMLEN := 0;
DOCOMMENT(NEWINPUTLINE, COLUMN - 1, INITCHAR);
END
ELSE
BEGIN
SYM := OPENPAREN;
NEWINPUTLINE := FALSE;
SYMBOLFOUND := TRUE;
END;
END
ELSE
DOCOMMENT(NEWINPUTLINE, COLUMN, CH);
END;
PROCEDURE GETSYM;
BEGIN
SYMLEN := 0;
SYMBOLFOUND := FALSE;
SYMWRITTEN := FALSE;
REPEAT
IF ENDFILE THEN
BEGIN
SYM := TEXTEND;
SYMBOLFOUND := TRUE
END
ELSE IF CH = ' ' THEN
SCANBLANKS
ELSE
BEGIN
CASE CH OF
'0'..'9', '$': NUMERICCHAR;
'A'..'Z', 'a'..'z', '_': ALPHACHAR;
')', '*', '/', '+', ',', '-', '.', ':', ';', '<', '=', '>', '[',
']', '^', '''', '#': SPECIALCHAR;
'(', '{': COMMENTCHAR;
'!', '&', '?', '\', '`', '|', '~', '}', '"', '@': PRINTCHAR;
ELSE
IF FORMATTING AND (CH = CHR(FF)) THEN
BEGIN
PRINTLINE(0);
PRINTCHAR;
SPACE(0);
CLEARBREAKS;
ENDLINE := TRUE;
END
ELSE
GETCHAR;
END
END;
UNTIL SYMBOLFOUND;
END;
PROCEDURE NEXTSYM;
BEGIN
IF SYM <> TEXTEND THEN
BEGIN
IF NOT SYMWRITTEN THEN
PUTSYM;
GETSYM;
END;
END;
PROCEDURE CHECK(FSYM: SETOFSYMS);
BEGIN
IF NOT (SYM IN FSYM) THEN
ABORT(SYNTAX);
END;
PROCEDURE CHECKSYM(DESIRED: SYMBOLS);
BEGIN
IF SYM = DESIRED THEN
NEXTSYM
ELSE
ABORT(SYNTAX);
END;
PROCEDURE NEXTONNEWLINE(SPACING, DELTA: INTEGER);
BEGIN
IF (BLANKLINES > 0) OR (CURRENTLINE = 0) THEN
SPACING := SPACING - 1;
REPEAT
FORMATLINE(INDENT);
SPACING := SPACING - 1;
UNTIL SPACING < 0;
INDENTPLUS(DELTA);
STATINDENT := INDENT;
NEXTSYM;
END;
PROCEDURE LOGSYMBOLSTART(VAR LOG: COLLOG);
BEGIN
WITH LOG DO
BEGIN
LOGCHAR := CHARCOUNT + 1;
LOGCOL := WRITECOL + 1;
LOGLINE := CURRENTLINE;
END;
END;
PROCEDURE BUNCH(START: COLLOG;
VAR SUCCESS: BOOLEAN);
BEGIN
WITH START DO
IF FORMATTING AND (CHARCOUNT - LOGCHAR < BUFSIZE) AND
(CHARCOUNT >= LOGCHAR) AND (LOGLINE + 1 = CURRENTLINE) AND
(WRITECOL - INDENT + LOGCOL < OUTLINELEN) THEN
BEGIN
WITH UNWRITTEN[LOGCHAR MOD BUFSIZE] DO
BEGIN
ACTIONIS := SPACES;
SPACING := 1;
WRITECOL := WRITECOL - INDENT + LOGCOL + 1;
END;
CURRENTLINE := CURRENTLINE - 1;
SUCCESS := TRUE;
END
ELSE
SUCCESS := FALSE;
END;
PROCEDURE BUNCHSTATEMENT(START: COLLOG);
VAR
TABINT: INTEGER;
NEXTTAB: INTEGER;
BEGIN
IF FORMATTING THEN
WITH START DO
BEGIN
TABINT := (OUTLINELEN - INDENT) DIV STATSPERLINE;
IF TABINT = 0 THEN
TABINT := 1;
IF LOGCOL = INDENT + 1 THEN
LOGCOL := INDENT;
NEXTTAB := (LOGCOL - INDENT + TABINT - 1) DIV TABINT * TABINT +
INDENT;
IF (NEXTTAB > INDENT) AND (LOGLINE + 1 = CURRENTLINE) AND
(CHARCOUNT - LOGCHAR < BUFSIZE) AND
(NEXTTAB + WRITECOL - INDENT <= OUTLINELEN) THEN
BEGIN
WITH UNWRITTEN[LOGCHAR MOD BUFSIZE] DO
BEGIN
ACTIONIS := SPACES;
SPACING := NEXTTAB - LOGCOL + 1;
END;
WRITECOL := NEXTTAB + WRITECOL - INDENT;
CURRENTLINE := CURRENTLINE - 1;
END;
END;
END;
PROCEDURE TERMINALSEMICOLON;
BEGIN
IF (SYM = SEMICOLON) AND NOT SYMWRITTEN THEN
PUTSYM;
END;
PROCEDURE STATEMENT;
FORWARD;
PROCEDURE EXPRESSION;
FORWARD;
PROCEDURE EXPRLIST(BREAKAT: INTEGER);
FORWARD;
PROCEDURE SCANTYPE;
FORWARD;
PROCEDURE DOBLOCK;
FORWARD;
PROCEDURE IDENTLIST;
BEGIN
WHILE SYM = IDENTIFIER DO
BEGIN
NEXTSYM;
IF SYM = COMMA THEN
BEGIN
NEXTSYM;
SETSYMBOLBREAK(0);
END;
END;
END;
PROCEDURE CONSTANT;
BEGIN
IF SYM IN [PLUS, MINUS] THEN
NEXTSYM;
CHECK(CONSTANTS - [PLUS, MINUS]);
NEXTSYM;
END;
PROCEDURE VARIABLE;
BEGIN
WHILE SYM IN [IDENTIFIER, PERIOD, POINTER, OPENBRACK] DO
BEGIN
IF SYM = OPENBRACK THEN
BEGIN
NEXTSYM;
EXPRLIST(0);
CHECKSYM(CLOSEBRACK);
END
ELSE
NEXTSYM;
END;
END;
PROCEDURE CONSTLIST;
BEGIN
WHILE SYM IN CONSTANTS DO
BEGIN
CONSTANT;
IF SYM = SUBRANGE THEN
BEGIN
NEXTSYM;
CONSTANT;
END;
IF SYM = COMMA THEN
BEGIN
NEXTSYM;
SETSYMBOLBREAK(0);
END;
END;
END;
PROCEDURE FACTOR;
BEGIN
IF SYM = OPENPAREN THEN
BEGIN
NEXTSYM;
EXPRLIST(0);
CHECKSYM(CLOSEPAREN);
IF SYM = COMMA THEN
SETSYMBOLBREAK(3);
END
ELSE IF SYM = OPENBRACK THEN
BEGIN
NEXTSYM;
WHILE SYM IN EXPRBEGSYS DO
BEGIN
EXPRLIST(1);
IF SYM = SUBRANGE THEN
NEXTSYM;
END;
CHECKSYM(CLOSEBRACK);
END
ELSE IF SYM = IDENTIFIER THEN
BEGIN
VARIABLE;
IF SYM = OPENPAREN THEN
BEGIN
PUTSYM;
IF WRITECOL <= THREEFOURTHLINE THEN
INDENTPLUS(WRITECOL - INDENT)
ELSE
INDENTPLUS(0);
NEXTSYM;
EXPRLIST(3);
CHECKSYM(CLOSEPAREN);
UNDENT;
END
END
ELSE
CONSTANT;
END;
PROCEDURE EXPRESSION;
BEGIN
WHILE SYM IN EXPRBEGSYS DO
BEGIN
IF SYM IN [PLUS, MINUS, NOTSYM, POINTER] THEN
NEXTSYM;
FACTOR;
IF SYM IN [ANDSYM, ORSYM, SHLSYM, SHRSYM, XORSYM] THEN
BEGIN
NEXTSYM;
SETSYMBOLBREAK(3);
END
ELSE IF SYM IN RELOPS THEN
BEGIN
NEXTSYM;
SETSYMBOLBREAK(2);
END
ELSE IF SYM IN ARITHOPS THEN
BEGIN
NEXTSYM;
SETSYMBOLBREAK(1);
END;
END;
END;
PROCEDURE EXPRLIST;
BEGIN
WHILE SYM IN EXPRBEGSYS + [COMMA] DO
BEGIN
IF SYM IN EXPRBEGSYS THEN
EXPRESSION;
IF (SYM = COMMA) OR (SYM = COLON) THEN
BEGIN
NEXTSYM;
SETSYMBOLBREAK(BREAKAT);
END;
END;
END;
PROCEDURE STATLIST;
VAR
STATTERMS: SETOFSYMS;
STATSTART: COLLOG;
FIRSTSTAT: BOOLEAN;
BEGIN
STATTERMS := STATSET + [SEMICOLON];
FIRSTSTAT := TRUE;
REPEAT
LOGSYMBOLSTART(STATSTART);
STATEMENT;
TERMINALSEMICOLON;
IF (STATSPERLINE > 1) AND NOT FIRSTSTAT THEN
BUNCHSTATEMENT(STATSTART);
IF SYM = SEMICOLON THEN
GETSYM;
FIRSTSTAT := FALSE;
UNTIL NOT (SYM IN STATTERMS);
END;
PROCEDURE DOBEGIN(PROCBLOCK: BOOLEAN);
VAR
TRIM: INTEGER;
BEGIN
RESETCHARCOUNT;
IF PROCBLOCK THEN
TRIM := TABSPACES
ELSE
TRIM := 0;
NEXTONNEWLINE(0, TRIM);
STATLIST;
UNDENT;
FORMATLINE(INDENT);
CHECKSYM(ENDSYM);
END;
PROCEDURE DOASSIGNCALL;
BEGIN
FORMATLINE(INDENT);
INDENTPLUS(CONTINUESPACES);
NEXTSYM;
IF SYM = COLON THEN
BEGIN
NEXTSYM;
STATEMENT;
END
ELSE
BEGIN
VARIABLE;
IF SYM = BECOMES THEN
BEGIN
NEXTSYM;
IF WRITECOL < THREEFOURTHLINE THEN
INDENTPLUS(WRITECOL - INDENT + 1)
ELSE
BEGIN
INDENTPLUS(0);
SETSYMBOLBREAK(0);
END;
EXPRESSION;
TERMINALSEMICOLON;
UNDENT;
END
ELSE IF SYM = OPENPAREN THEN
BEGIN
NEXTSYM;
IF WRITECOL <= THREEFOURTHLINE THEN
INDENTPLUS(WRITECOL - INDENT)
ELSE
INDENTPLUS(0);
EXPRLIST(3);
CHECKSYM(CLOSEPAREN);
TERMINALSEMICOLON;
UNDENT;
END
ELSE
TERMINALSEMICOLON;
UNDENT;
END;
END;
PROCEDURE DOGOTO;
BEGIN
FORMATLINE(INDENT);
NEXTSYM;
IF SYM IN [NUMBER, IDENTIFIER] THEN
NEXTSYM
ELSE
ABORT(SYNTAX);
TERMINALSEMICOLON;
END;
PROCEDURE DOINLINE;
BEGIN
FORMATLINE(INDENT);
INDENTPLUS(CONTINUESPACES);
NEXTSYM;
IF SYM <> OPENPAREN THEN
ABORT(SYNTAX);
REPEAT
NEXTSYM;
IF SYM = MULT THEN
BEGIN
NEXTSYM;
IF SYM IN CONSTANTS THEN
CONSTANT;
END
ELSE
CONSTANT;
UNTIL SYM <> DIVIDE;
CHECKSYM(CLOSEPAREN);
TERMINALSEMICOLON;
UNDENT;
END;
PROCEDURE DOWHILE;
VAR
WHILESTART: COLLOG;
STARTLINE, ENDLINE: INTEGER;
SUCCESSFUL: BOOLEAN;
BEGIN
RESETCHARCOUNT;
FORMATLINE(INDENT);
NEXTSYM;
IF WRITECOL < THREEFOURTHLINE THEN
INDENTPLUS(WRITECOL - INDENT + 1)
ELSE
INDENTPLUS(CONTINUESPACES);
STARTLINE := CURRENTLINE;
EXPRESSION;
CHECKSYM(DOSYM);
UNDENT;
INDENTPLUS(TABSPACES);
ENDLINE := CURRENTLINE;
LOGSYMBOLSTART(WHILESTART);
STATINDENT := INDENT;
STATEMENT;
IF BUNCHING AND (STARTLINE = ENDLINE) THEN
BUNCH(WHILESTART, SUCCESSFUL);
UNDENT;
END;
PROCEDURE DOWITH;
VAR
STARTLINE, ENDLINE: INTEGER;
WITHSTART: COLLOG;
SUCCESSFUL: BOOLEAN;
BEGIN
RESETCHARCOUNT;
FORMATLINE(INDENT);
NEXTSYM;
IF WRITECOL < THREEFOURTHLINE THEN
INDENTPLUS(WRITECOL - INDENT + 1)
ELSE
INDENTPLUS(CONTINUESPACES);
STARTLINE := CURRENTLINE;
EXPRLIST(3);
CHECKSYM(DOSYM);
UNDENT;
INDENTPLUS(TABSPACES);
STATINDENT := INDENT;
ENDLINE := CURRENTLINE;
LOGSYMBOLSTART(WITHSTART);
STATEMENT;
IF BUNCHING AND (STARTLINE = ENDLINE) THEN
BUNCH(WITHSTART, SUCCESSFUL);
UNDENT;
END;
PROCEDURE DOIF(PREVELSE: BOOLEAN);
VAR
IFSTART: COLLOG;
STARTLINE, ENDLINE: INTEGER;
SUCCESSFUL: BOOLEAN;
BEGIN
RESETCHARCOUNT;
IF NOT PREVELSE THEN
FORMATLINE(INDENT);
NEXTSYM;
IF WRITECOL < THREEFOURTHLINE THEN
INDENTPLUS(WRITECOL - INDENT + 1)
ELSE
INDENTPLUS(CONTINUESPACES);
STARTLINE := CURRENTLINE;
EXPRESSION;
CHECKSYM(THENSYM);
UNDENT;
INDENTPLUS(TABSPACES);
ENDLINE := CURRENTLINE;
LOGSYMBOLSTART(IFSTART);
STATEMENT;
IF BUNCHING AND (STARTLINE = ENDLINE) THEN
BUNCH(IFSTART, SUCCESSFUL);
UNDENT;
STATINDENT := INDENT;
IF SYM = ELSESYM THEN
BEGIN
FORMATLINE(INDENT);
NEXTSYM;
IF SYM = IFSYM THEN
DOIF(TRUE)
ELSE
BEGIN
INDENTPLUS(TABSPACES);
LOGSYMBOLSTART(IFSTART);
STATEMENT;
IF BUNCHING THEN
BUNCH(IFSTART, SUCCESSFUL);
UNDENT;
END;
END;
END;
PROCEDURE DOCASE;
VAR
CASESTART: COLLOG;
SUCCESSFUL: BOOLEAN;
LABSTART, LABEND: INTEGER;
BEGIN
RESETCHARCOUNT;
FORMATLINE(INDENT);
NEXTSYM;
IF WRITECOL < THREEFOURTHLINE THEN
INDENTPLUS(WRITECOL - INDENT + 1)
ELSE
INDENTPLUS(CONTINUESPACES);
EXPRESSION;
CHECKSYM(OFSYM);
UNDENT;
INDENTPLUS(TABSPACES);
STATINDENT := INDENT;
WHILE NOT (SYM IN [ENDSYM, ELSESYM]) DO
BEGIN
IF SYM IN CONSTANTS THEN
BEGIN
FORMATLINE(INDENT);
LABSTART := CURRENTLINE;
CONSTLIST;
CHECKSYM(COLON);
LABEND := CURRENTLINE;
INDENTPLUS(TABSPACES);
LOGSYMBOLSTART(CASESTART);
STATEMENT;
BUNCH(CASESTART, SUCCESSFUL);
UNDENT;
STATINDENT := INDENT;
END;
IF SYM = SEMICOLON THEN
NEXTSYM;
CHECK(CONSTANTS + [ENDSYM, SEMICOLON, ELSESYM]);
END;
IF SYM = ELSESYM THEN
BEGIN
NEXTONNEWLINE(0, TABSPACES);
LOGSYMBOLSTART(CASESTART);
STATLIST;
BUNCH(CASESTART, SUCCESSFUL);
UNDENT;
END;
UNDENT;
FORMATLINE(INDENT);
CHECKSYM(ENDSYM);
END;
PROCEDURE DOREPEAT;
BEGIN
RESETCHARCOUNT;
NEXTONNEWLINE(0, TABSPACES);
STATLIST;
UNDENT;
STATINDENT := INDENT;
FORMATLINE(INDENT);
CHECKSYM(UNTILSYM);
IF WRITECOL < THREEFOURTHLINE THEN
INDENTPLUS(WRITECOL - INDENT + 1)
ELSE
INDENTPLUS(CONTINUESPACES);
EXPRESSION;
TERMINALSEMICOLON;
UNDENT;
END;
PROCEDURE DOFOR;
VAR
STARTLINE, ENDLINE: INTEGER;
FORSTART: COLLOG;
SUCCESSFUL: BOOLEAN;
BEGIN
RESETCHARCOUNT;
NEXTONNEWLINE(0, CONTINUESPACES);
STARTLINE := CURRENTLINE;
CHECKSYM(IDENTIFIER);
CHECKSYM(BECOMES);
EXPRESSION;
CHECK([TOSYM, DOWNTOSYM]);
NEXTSYM;
EXPRESSION;
CHECKSYM(DOSYM);
UNDENT;
INDENTPLUS(TABSPACES);
ENDLINE := CURRENTLINE;
LOGSYMBOLSTART(FORSTART);
STATEMENT;
IF BUNCHING AND (STARTLINE = ENDLINE) THEN
BUNCH(FORSTART, SUCCESSFUL);
UNDENT;
END;
PROCEDURE STATEMENT;
BEGIN
STATINDENT := INDENT;
IF SYM = NUMBER THEN
BEGIN
INDENTPLUS( - TABSPACES);
FORMATLINE(INDENT);
NEXTSYM;
CHECKSYM(COLON);
UNDENT;
END;
IF SYM IN (STATSET - [NUMBER]) THEN
CASE SYM OF
BEGINSYM: DOBEGIN(TRUE);
CASESYM: DOCASE;
FORSYM: DOFOR;
GOTOSYM: DOGOTO;
IDENTIFIER: DOASSIGNCALL;
IFSYM: DOIF(FALSE);
INLINESYM: DOINLINE;
REPEATSYM: DOREPEAT;
WHILESYM: DOWHILE;
WITHSYM: DOWITH;
END;
STATINDENT := INDENT;
END;
PROCEDURE PARAMETERS;
BEGIN
IF WRITECOL > ONEHALFLINE THEN
FORMATLINE(INDENT + 2 * TABSPACES);
NEXTSYM;
INDENTPLUS(WRITECOL - INDENT);
WHILE SYM IN [IDENTIFIER, VARSYM] DO
BEGIN
IF SYM <> IDENTIFIER THEN
NEXTSYM;
IF SYM <> IDENTIFIER THEN
ABORT(SYNTAX);
INDENTPLUS(CONTINUESPACES);
IDENTLIST;
UNDENT;
IF SYM = COLON THEN
BEGIN
NEXTSYM;
SCANTYPE;
END;
IF SYM = SEMICOLON THEN
BEGIN
NEXTSYM;
FORMATLINE(INDENT);
END;
END;
CHECKSYM(CLOSEPAREN);
TERMINALSEMICOLON;
UNDENT;
STATINDENT := INDENT;
END;
PROCEDURE FIELDLIST;
VAR
INVARPART: BOOLEAN;
LABELSTART, LABELEND: INTEGER;
CASESTART: COLLOG;
SUCCESSFUL: BOOLEAN;
BEGIN
INVARPART := FALSE;
WHILE SYM = IDENTIFIER DO
BEGIN
INVARPART := TRUE;
INDENTPLUS(CONTINUESPACES);
IDENTLIST;
CHECKSYM(COLON);
UNDENT;
SCANTYPE;
IF SYM = SEMICOLON THEN
NEXTSYM;
IF SYM = IDENTIFIER THEN
FORMATLINE(INDENT);
END;
IF SYM = CASESYM THEN
BEGIN
IF INVARPART THEN
FORMATLINE(INDENT);
NEXTSYM;
INDENTPLUS(CONTINUESPACES);
IF SYM = IDENTIFIER THEN
NEXTSYM
ELSE
SCANTYPE;
IF SYM = COLON THEN
BEGIN
NEXTSYM;
SCANTYPE
END;
CHECKSYM(OFSYM);
UNDENT;
INDENTPLUS(TABSPACES);
STATINDENT := INDENT;
FORMATLINE(INDENT);
REPEAT
LABELSTART := CURRENTLINE;
CONSTLIST;
CHECKSYM(COLON);
LABELEND := CURRENTLINE;
INDENTPLUS(TABSPACES);
STATINDENT := INDENT;
LOGSYMBOLSTART(CASESTART);
FORMATLINE(INDENT);
CHECKSYM(OPENPAREN);
INDENTPLUS(1);
FIELDLIST;
UNDENT;
CHECKSYM(CLOSEPAREN);
UNDENT;
STATINDENT := INDENT;
IF SYM = SEMICOLON THEN
NEXTSYM;
IF BUNCHING AND (LABELSTART = LABELEND) THEN
BUNCH(CASESTART, SUCCESSFUL);
IF NOT (SYM IN [ENDSYM, CLOSEPAREN]) THEN
FORMATLINE(INDENT);
UNTIL NOT (SYM IN CONSTANTS);
UNDENT;
STATINDENT := INDENT;
END
END;
PROCEDURE RECORDTYPE(PACKEDSTART: COLLOG);
BEGIN
INDENTPLUS(TABSPACES);
WITH PACKEDSTART DO
IF FORMATTING AND (LOGCHAR <> 0) AND
(CHARCOUNT - LOGCHAR < BUFSIZE) THEN
WITH UNWRITTEN[LOGCHAR MOD BUFSIZE] DO
BEGIN
ACTIONIS := BEGINLINE;
SPACING := INDENT;
WRITECOL := INDENT + WRITECOL - LOGCOL;
CURRENTLINE := CURRENTLINE + 1;
END
ELSE
FORMATLINE(INDENT);
NEXTSYM;
INDENTPLUS(TABSPACES);
STATINDENT := INDENT;
FORMATLINE(INDENT);
FIELDLIST;
UNDENT;
FORMATLINE(INDENT);
CHECKSYM(ENDSYM);
TERMINALSEMICOLON;
UNDENT;
END;
PROCEDURE ARRAYTYPE;
BEGIN
INDENTPLUS(TABSPACES);
NEXTSYM;
SETSYMBOLBREAK(0);
CHECKSYM(OPENBRACK);
WHILE SYM IN CONSTANTS DO
BEGIN
CONSTANT;
IF SYM = SUBRANGE THEN
BEGIN
NEXTSYM;
CONSTANT;
END;
IF (SYM = COMMA) OR (SYM = SEMICOLON) THEN
BEGIN
NEXTSYM;
SETSYMBOLBREAK(0);
END;
END;
CHECKSYM(CLOSEBRACK);
CHECKSYM(OFSYM);
SCANTYPE;
TERMINALSEMICOLON;
UNDENT;
END;
PROCEDURE STRING_TYPE;
BEGIN
NEXTSYM;
IF ((SYM <> SEMICOLON) AND (SYM <> CLOSEPAREN)) THEN
BEGIN
SETSYMBOLBREAK(0);
CHECKSYM(OPENBRACK);
CONSTANT;
CHECKSYM(CLOSEBRACK);
END;
END;
PROCEDURE ENUMTYPE;
BEGIN
NEXTSYM;
IF WRITECOL <= THREEFOURTHLINE THEN
INDENTPLUS(WRITECOL - INDENT)
ELSE
INDENTPLUS(CONTINUESPACES);
IDENTLIST;
CHECKSYM(CLOSEPAREN);
TERMINALSEMICOLON;
UNDENT;
END;
PROCEDURE SCANTYPE;
VAR
PACKEDSTART: COLLOG;
BEGIN
INDENTPLUS(CONTINUESPACES);
IF SYM = PACKEDSYM THEN
BEGIN
LOGSYMBOLSTART(PACKEDSTART);
NEXTSYM;
END
ELSE
PACKEDSTART.LOGCHAR := 0;
UNDENT;
CHECK(TYPEBEGSYS);
CASE SYM OF
OPENPAREN: ENUMTYPE;
ARRAYSYM: ARRAYTYPE;
STRINGSYM: STRING_TYPE;
FILESYM:
BEGIN
NEXTSYM;
IF SYM = OFSYM THEN
BEGIN
NEXTSYM;
SCANTYPE;
END;
END;
SETSYM:
BEGIN
NEXTSYM;
CHECKSYM(OFSYM);
SCANTYPE;
END;
IDENTIFIER, NUMBER, PLUS, MINUS, STRCONST:
BEGIN
CONSTANT;
IF SYM = SUBRANGE THEN
BEGIN
NEXTSYM;
CONSTANT;
END;
END;
POINTER:
BEGIN
NEXTSYM;
SCANTYPE;
END;
RECORDSYM: RECORDTYPE(PACKEDSTART);
END;
STATINDENT := INDENT;
END;
PROCEDURE DOLABEL;
BEGIN
RESETCHARCOUNT;
NEXTONNEWLINE(1, TABSPACES);
FORMATLINE(INDENT);
WHILE SYM IN [NUMBER, IDENTIFIER] DO
BEGIN
NEXTSYM;
IF SYM = COMMA THEN
NEXTSYM;
END;
CHECKSYM(SEMICOLON);
UNDENT;
END;
PROCEDURE STRUCTUREDCONSTANT;
PROCEDURE ARRAYORRECORDCONSTANT(BREAKAT: INTEGER);
BEGIN
REPEAT
NEXTSYM;
IF SYM = IDENTIFIER THEN
BEGIN
NEXTSYM;
IF SYM = COLON THEN
BEGIN
NEXTSYM;
IF SYM = OPENPAREN THEN
ARRAYORRECORDCONSTANT(BREAKAT + 1)
ELSE
CONSTANT;
END;
END
ELSE IF SYM = OPENPAREN THEN
ARRAYORRECORDCONSTANT(BREAKAT + 1)
ELSE
CONSTANT;
UNTIL NOT ((SYM = COMMA) OR (SYM = SEMICOLON));
CHECKSYM(CLOSEPAREN);
END;
BEGIN
IF SYM = OPENPAREN THEN
ARRAYORRECORDCONSTANT(0)
ELSE IF SYM = OPENBRACK THEN
BEGIN
REPEAT
NEXTSYM;
CONSTANT;
IF SYM = SUBRANGE THEN
BEGIN
NEXTSYM;
CONSTANT;
END;
UNTIL SYM <> COMMA;
CHECKSYM(CLOSEBRACK);
END
ELSE
CONSTANT;
END;
PROCEDURE DOCONST;
VAR
CONSTSTART: COLLOG;
FIRSTCONST: BOOLEAN;
BEGIN
INDECLARATION := TRUE;
RESETCHARCOUNT;
NEXTONNEWLINE(1, TABSPACES);
FIRSTCONST := TRUE;
WHILE SYM = IDENTIFIER DO
BEGIN
LOGSYMBOLSTART(CONSTSTART);
FORMATLINE(INDENT);
NEXTSYM;
IF SYM = COLON THEN
BEGIN
NEXTSYM;
SCANTYPE;
END;
CHECKSYM(EQUAL);
STRUCTUREDCONSTANT;
IF SYM = SEMICOLON THEN
PUTSYM
ELSE
ABORT(SYNTAX);
IF (STATSPERLINE > 1) AND NOT FIRSTCONST THEN
BUNCHSTATEMENT(CONSTSTART);
NEXTSYM;
FIRSTCONST := FALSE;
END;
UNDENT;
STATINDENT := INDENT;
INDECLARATION := FALSE;
END;
PROCEDURE DOTYPE;
BEGIN
INTYPEORVARDCL := TRUE;
INDECLARATION := TRUE;
NEXTONNEWLINE(1, TABSPACES);
WHILE SYM = IDENTIFIER DO
BEGIN
RESETCHARCOUNT;
FORMATLINE(INDENT);
NEXTSYM;
CHECKSYM(EQUAL);
SCANTYPE;
CHECKSYM(SEMICOLON);
END;
UNDENT;
STATINDENT := INDENT;
INTYPEORVARDCL := FALSE;
INDECLARATION := FALSE;
END;
PROCEDURE DOVAR;
BEGIN
INTYPEORVARDCL := TRUE;
INDECLARATION := TRUE;
NEXTONNEWLINE(1, TABSPACES);
WHILE SYM = IDENTIFIER DO
BEGIN
RESETCHARCOUNT;
FORMATLINE(INDENT);
INDENTPLUS(CONTINUESPACES);
CHECK([IDENTIFIER]);
IDENTLIST;
CHECKSYM(COLON);
UNDENT;
SCANTYPE;
IF SYM = ABSOLUTESYM THEN
BEGIN
NEXTSYM;
CONSTANT;
IF SYM = COLON THEN
BEGIN
NEXTSYM;
CONSTANT;
END;
END;
CHECKSYM(SEMICOLON);
END;
UNDENT;
STATINDENT := INDENT;
INTYPEORVARDCL := FALSE;
INDECLARATION := FALSE;
NEWLINE(1);
END;
PROCEDURE DOPROGRAM;
BEGIN
NEXTONNEWLINE(0, CONTINUESPACES);
CHECKSYM(IDENTIFIER);
IF SYM = OPENPAREN THEN
BEGIN
NEXTSYM;
WHILE SYM = IDENTIFIER DO
BEGIN
NEXTSYM;
IF SYM = COMMA THEN
BEGIN
NEXTSYM;
SETSYMBOLBREAK(0);
END;
END;
CHECKSYM(CLOSEPAREN);
END;
CHECKSYM(SEMICOLON);
UNDENT;
INDENTPLUS(TABSPACES);
DOBLOCK;
IF SYM = PERIOD THEN
NEXTSYM;
UNDENT;
END;
PROCEDURE DOPROCEDURE;
VAR
STARTSYM: SYMBOLS;
BEGIN
RESETCHARCOUNT;
STARTSYM := SYM;
NEXTONNEWLINE(PARAGRAFINDENT, CONTINUESPACES);
IF STARTSYM = OVERLAYSYM THEN
BEGIN
STARTSYM := SYM;
IF (SYM <> PROCEDURESYM) AND (SYM <> FUNCTIONSYM) THEN
ABORT(SYNTAX);
NEXTSYM;
END;
CHECKSYM(IDENTIFIER);
IF SYM = OPENPAREN THEN
PARAMETERS;
IF STARTSYM = FUNCTIONSYM THEN
IF SYM = COLON THEN
BEGIN
CHECKSYM(COLON);
CHECKSYM(IDENTIFIER);
END;
TERMINALSEMICOLON;
UNDENT;
CHECKSYM(SEMICOLON);
INDENTPLUS(TABSPACES);
IF SYM IN [EXTERNSYM, FORWARDSYM] THEN
BEGIN
FORMATLINE(INDENT);
IF SYM = EXTERNSYM THEN
BEGIN
NEXTSYM;
IF SYM <> STRCONST THEN
ABORT(SYNTAX);
END;
NEXTSYM;
END
ELSE IF SYM IN BLOCKBEGSYS THEN
DOBLOCK
ELSE
ABORT(SYNTAX);
IF SYM = SEMICOLON THEN
BEGIN
PUTSYM;
UNDENT;
STATINDENT := INDENT;
NEXTSYM;
END
ELSE
ABORT(SYNTAX);
END;
PROCEDURE DOUSES;
BEGIN
RESETCHARCOUNT;
UNDENT;
NEXTONNEWLINE(1, TABSPACES);
FORMATLINE(INDENT);
WHILE SYM IN [COMMA, IDENTIFIER] DO
BEGIN
NEXTSYM;
IF SYM = COMMA THEN
NEXTSYM;
END;
CHECKSYM(SEMICOLON);
UNDENT;
END;
PROCEDURE DOBLOCK;
BEGIN
STATINDENT := INDENT;
IF SYM = BEGINSYM THEN
NEWLINE(1);
WHILE SYM IN HEADINGBEGSYS DO
BEGIN
CASE SYM OF
LABELSYM: DOLABEL;
CONSTSYM: DOCONST;
USESSYM: DOUSES;
TYPESYM: DOTYPE;
VARSYM: DOVAR;
OVERLAYSYM, PROCEDURESYM, FUNCTIONSYM: DOPROCEDURE;
END;
STATINDENT := INDENT;
END;
IF SYM = BEGINSYM THEN
DOBEGIN(TRUE);
END;
PROCEDURE PROCESSTEXT;
BEGIN
CLEARBREAKS;
IF SYM = PROGRAMSYM THEN
DOPROGRAM
ELSE IF SYM IN BLOCKBEGSYS THEN
BEGIN
DOBLOCK;
IF SYM = SEMICOLON THEN
NEXTSYM;
IF SYM = PERIOD THEN
NEXTSYM;
END
ELSE IF SYM IN STATSET THEN
STATLIST;
CHECK([TEXTEND]);
FLUSHBUFFER;
END;
BEGIN
INITIALIZE;
CSI;
GETCHAR;
GETSYM;
PROCESSTEXT;
QUIT;
END.